package com.reformer.commons.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


public class XMLUtil {

    private static final Log LOG = LogFactory.getLog(XMLUtil.class);

    /**
     * 将xml转化为Map对象
     *
     * @param xmlString xml字符串
     * @return Map
     */
    public static Map<String, String> parseMap(String xmlString) {
        try {
            Map<String, String> map = new HashMap<String, String>();
            Document document = DocumentHelper.parseText(xmlString);
            Element root = document.getRootElement();
            List list = root.elements();
            // 递归方法
            for (Iterator it = list.iterator(); it.hasNext(); ) {
                Element e = (Element) it.next();
                map.put(e.getName(), e.getTextTrim());
            }
            return map;
        } catch (Exception e) {
            LOG.error(e.toString(), e);
            return null;
        }
    }

    /**
     * 递归解析，适用于多层xml字符串解析
     * @param xmlString
     * @return
     */
    public static Map<String, Object> parseRRecursive(String xmlString) {
        try {
            Map<String, String> map = new HashMap<String, String>();
            Document document = DocumentHelper.parseText(xmlString);
            return parseMap(document.getRootElement());
        } catch (Exception e) {
            LOG.error(e.toString(), e);
            return null;
        }
    }

    private static Map<String, Object > parseMap(Element element){
        Map<String, Object> map = new HashMap<>();
        List list = element.elements();
        // 递归方法
        for (Iterator it = list.iterator(); it.hasNext(); ) {
            Element e = (Element) it.next();
            if (e.elements().size() > 0) {
                map.put(e.getName(), parseMap(e));
            }else{
                map.put(e.getName(), e.getTextTrim());
            }
        }
        return map;
    }

    public static String formatXML(Map xmlObj) {
        return formatXML(xmlObj, "xml");
    }

    public static String formatXML(Map xmlObj, String rootTag) {
        StringBuilder sb = new StringBuilder("<").append(rootTag).append(">");
        Iterator it = xmlObj.entrySet().iterator();
        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            Object k = entry.getKey();
            Object v = entry.getValue();
            if (k != null && v != null) {
                String key=k.toString().trim();
                String value=v.toString().trim();
                sb.append("<").append(key).append(">");
                sb.append("<![CDATA[").append(value).append("]]>");
                sb.append("</").append(key).append(">");
            }
        }
        sb.append("</").append(rootTag).append(">");
        return sb.toString();
    }

    public static String formatXMLWithoutCDATA(Map xmlObj) {
        return formatXMLWithoutCDATA(xmlObj, "xml");
    }

    public static String formatXMLWithoutCDATA(Map xmlObj, String rootTag) {
        StringBuilder sb = new StringBuilder("<").append(rootTag).append(">");
        Iterator it = xmlObj.entrySet().iterator();
        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            Object k = entry.getKey();
            Object v = entry.getValue();
            if (k != null && v != null) {
                String key=k.toString().trim();
                String value=v.toString().trim();
                sb.append("<").append(key).append(">");
                sb.append(value);
                sb.append("</").append(key).append(">");
            }
        }
        sb.append("</").append(rootTag).append(">");
        return sb.toString();
    }
    private static Document parse2Document(String xmlFilePath) {
        SAXReader reader = new SAXReader();
        Document document = null;
        try {
            InputStream in = XMLUtil.class.getResourceAsStream(xmlFilePath);
            document = reader.read(in);
        } catch (DocumentException e) {
            LOG.error(e.toString(), e);
        }
        return document;
    }

    /**
     * 读xml文件
     *
     * @param xmlFile xmlFile
     * @return
     * @author shang
     */
    public static Document readXML(File xmlFile) {
        try {
            SAXReader reader = new SAXReader();
            return reader.read(xmlFile);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
